package com.kfd.mvc;

import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * 映射器（包含了大量网址和方法的对应关系）
 */
public class HandlerMapping {

    private static Map<String,MVCMping> data = new HashMap<>();

    public static MVCMping get(String url){
        return data.get(url);
    }

    public static void load(InputStream is){
        //将输入流加载到properties中map集合中
        Properties properties = new Properties();
        try {
            properties.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //获取配置文件中的一个个的类
        Collection<Object> values = properties.values();
        for (Object value : values) {
            String className = (String) value;
            try {
                //加载配置文件中描述的每一个类
                Class<?> c = Class.forName(className);
                //创建这个类的对象
                Object obj = c.getConstructor().newInstance();
                //获取这个类的所有共有的方法
                Method[] methods = c.getMethods();
                for (Method method : methods) {
                    //获得这个方法的所有注解
                    Annotation[] annotations = method.getAnnotations();
                    if(annotations != null){
                        for (Annotation annotation : annotations) {

                            if(annotation instanceof ResponseBody){
                                //如果这个注解是ResponseBody，说明此方法是返回字符串给客户端

                                //创建这个对象用于存放到map，入参分别是这个类，类声明这个注解的方法，这个方法的返回类型
                                MVCMping mvcMping = new MVCMping(obj,method,ResponseType.TEXT);
                                //存放到map中
                                MVCMping put = data.put(((ResponseBody) annotation).value(), mvcMping);
                                if(put != null){
                                    //说明是覆盖，存在重复的请求地址
                                    throw new RuntimeException("请求地址重复："+((ResponseBody) annotation).value());
                                }
                            }else if(annotation instanceof ResponseView){
                                //如果这个注解是ResponseView，说明此方法是返回页面给客户端

                                //创建这个对象用于存放到map，入参分别是这个类，类声明这个注解的方法，这个方法的返回类型
                                MVCMping mvcMping = new MVCMping(obj,method,ResponseType.VIEW);

                                MVCMping put = data.put(((ResponseView) annotation).value(), mvcMping);
                                if(put != null){
                                    //说明是覆盖，存在重复的请求地址
                                    throw new RuntimeException("请求地址重复："+((ResponseView) annotation).value());
                                }
                            }
                        }
                    }

                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }


    };

    /**
     *映射对象，每一个对象封装了一个方法，用于处理请求
     */
    public static class MVCMping{
        private Object obj;
        private Method method;
        private ResponseType type;

        public MVCMping() {
        }

        public MVCMping(Object obj, Method method, ResponseType type) {
            this.obj = obj;
            this.method = method;
            this.type = type;
        }

        public Object getObj() {
            return obj;
        }

        public void setObj(Object obj) {
            this.obj = obj;
        }

        public Method getMethod() {
            return method;
        }

        public void setMethod(Method method) {
            this.method = method;
        }

        public ResponseType getType() {
            return type;
        }

        public void setType(ResponseType type) {
            this.type = type;
        }
    }
}
